using System;
using System.Data;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.TTC;

namespace OracleInternal.ServiceObjects
{
	internal class OracleTransactionImpl
	{
		private OracleConnectionImpl m_connectionImpl;

		private IsolationLevel m_isolationLevel;

		internal OracleTransactionImpl(OracleConnectionImpl connectionImpl, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.ctor);
			}
			m_connectionImpl = connectionImpl;
			m_isolationLevel = isolationLevel;
			if (m_connectionImpl.m_currentIsolationLvl != m_isolationLevel)
			{
				m_connectionImpl.SwitchIsolationLevel(isolationLevel);
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.ctor);
			}
		}

		internal void Commit(OracleConnection connection, ref OracleLogicalTransaction oracleLogicalTransaction)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Commit);
			}
			try
			{
				m_connectionImpl.m_connectionFreeToUseEvent.WaitOne();
				m_connectionImpl.AddAllPiggyBackRequests();
				oracleLogicalTransaction = connection?.OracleLogicalTransaction;
				TTCSimpleOperations simpleOperationsObject = m_connectionImpl.SimpleOperationsObject;
				simpleOperationsObject.SetFunctionCode(14);
				simpleOperationsObject.WriteMessage();
				simpleOperationsObject.ReadResponse();
				TTCError tTCErrorObject = simpleOperationsObject.m_marshallingEngine.TTCErrorObject;
				if (tTCErrorObject.m_retCode != 0)
				{
					char[] t = tTCErrorObject.m_marshallingEngine.m_charArrayPooler.Dequeue();
					string errMsg = tTCErrorObject.m_marshallingEngine.m_dbCharSetConv.ConvertBytesToString(tTCErrorObject.m_errorMsg, 0, tTCErrorObject.m_errorMsg.Length, t);
					tTCErrorObject.m_marshallingEngine.m_charArrayPooler.Enqueue(ref t);
					throw new OracleException(tTCErrorObject.m_retCode, string.Empty, string.Empty, errMsg);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Commit, ex);
				throw;
			}
			finally
			{
				m_connectionImpl.m_connectionFreeToUseEvent.Set();
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Commit);
				}
			}
		}

		internal void Rollback(OracleConnection connection, ref OracleLogicalTransaction oracleLogicalTransaction)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Rollback);
			}
			try
			{
				m_connectionImpl.m_connectionFreeToUseEvent.WaitOne();
				m_connectionImpl.AddAllPiggyBackRequests();
				oracleLogicalTransaction = ((connection != null && !connection.bConnectionforTxnStatus && !connection.bIgnoreLogicalTransaction) ? connection.OracleLogicalTransaction : null);
				TTCSimpleOperations simpleOperationsObject = m_connectionImpl.SimpleOperationsObject;
				simpleOperationsObject.SetFunctionCode(15);
				simpleOperationsObject.WriteMessage();
				simpleOperationsObject.ReadResponse();
				TTCError tTCErrorObject = simpleOperationsObject.m_marshallingEngine.TTCErrorObject;
				if (tTCErrorObject.m_retCode != 0)
				{
					char[] t = tTCErrorObject.m_marshallingEngine.m_charArrayPooler.Dequeue();
					string errMsg = tTCErrorObject.m_marshallingEngine.m_dbCharSetConv.ConvertBytesToString(tTCErrorObject.m_errorMsg, 0, tTCErrorObject.m_errorMsg.Length, t);
					tTCErrorObject.m_marshallingEngine.m_charArrayPooler.Enqueue(ref t);
					throw new OracleException(tTCErrorObject.m_retCode, string.Empty, string.Empty, errMsg);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Rollback, ex);
				throw;
			}
			finally
			{
				m_connectionImpl.m_connectionFreeToUseEvent.Set();
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.OracleTransactionImpl, OracleTraceFuncName.Rollback);
				}
			}
		}
	}
}
